home *** CD-ROM | disk | FTP | other *** search
- /*
- * Blob Manager Demonstration: Coin Swap module
- *
- * This has a linear board with either 5, 7 or 9 pieces. The middle
- * piece is always empty, the pieces on one end are filled with black
- * coins, the pieces on the other end are filled with white coins.
- * The object is to swap the coins. A coin can slide into an empty
- * piece next to it, or jump over a single coin to land on an empty
- * piece.
- *
- * A menu allows the number of coins to be chosen. To win, the coins
- * have to be swapped in a specific number of moves.
- *
- * 26 July 1986 Paul DuBois
- */
-
- # include "TransSkel.h"
-
- # include "BlobMgr.h"
- # include "BlobDemo.h"
-
-
- # define vMessage 10
- # define vPiece 30
- # define maxPieces 9
- # define pieceSize 24
- # define pieceGap 1
-
-
- static WindowPtr wind;
- static MenuHandle cnfgMenu;
- static BlobSetHandle donors = nil;
- static BlobSetHandle receptors = nil;
- static short hMid;
- static Str255 statusStr = "\p";
-
- static short nPieces = 5;
- static short nMoves = 8;
- static BlobHandle piece[maxPieces];
- static short moves;
- static Boolean pause;
-
-
- static void
- StatusMesg (StringPtr s)
- {
- Rect r;
-
- SetRect (&r, hMid - 60, vMessage, hMid + 60, vMessage+16);
- TextBox (s+1, (long) s[0], &r, teJustCenter);
- StrCpy (statusStr, s);
- }
-
-
- /*
- * Reset to start state. This recreates the board each time. All the
- * blobs in the board require explicit matches except the middle one.
- */
-
- static void
- Reset (void)
- {
- BlobHandle b;
- Rect r;
- short i, h;
- Str255 s;
-
- InvalRect (&wind->portRect); /* force update when done resetting */
- pause = false;
- moves = nMoves;
- MovesLeft (moves, s);
- StatusMesg (s);
-
- if (receptors != nil) /* clobber any existing receptor set */
- {
- HideBlobSet (receptors);
- DisposeBlobSet (receptors);
- }
- receptors = NewBlobSet ();
-
- h = hMid - (nPieces * (pieceSize + pieceGap) - pieceGap) / 2;
- for (i = 0; i < nPieces; ++i)
- {
- b = NewBlob (receptors, true, 0, i != (nPieces - 1) / 2, 0L);
- piece[i] = b;
- OpenBlob ();
- SetRect (&r, h, vPiece, h + pieceSize, vPiece + pieceSize);
- EraseRect (&r);
- FrameRect (&r);
- CloseRectBlob (b, &r, &r);
- h += pieceSize + pieceGap;
- if (i < (nPieces - 1) / 2)
- {
- GlueGlob (GetBlobHandle (donors, 0), b);
- NewBlobMatch (GetBlobHandle (donors, 1), b);
- }
- else if (i > (nPieces - 1) / 2)
- {
- GlueGlob (GetBlobHandle (donors, 1), b);
- NewBlobMatch (GetBlobHandle (donors, 0), b);
- }
- }
- }
-
-
- static void
- SwapPause (StringPtr msg)
- {
- StatusMesg (msg);
- pause = true;
- }
-
-
- static pascal void
- Mouse (Point pt, long t, short mods)
- {
- Str255 s;
- short i;
-
- /*
- * Freeze all the pieces that can't be moved, then call BlobClick().
- */
- for (i = 0; i < nPieces; ++i)
- {
- ThawBlob (piece[i]);
- if (BGlob (piece[i]) == nil) continue;
- if (i > 0 && BGlob (piece[i-1]) == nil) continue;
- if (i > 1 && BGlob (piece[i-2]) == nil) continue;
- if (i < nPieces - 1 && BGlob (piece[i+1]) == nil) continue;
- if (i < nPieces - 2 && BGlob (piece[i+2]) == nil) continue;
- FreezeBlob (piece[i]);
- }
- if (!pause)
- {
- BlobClick (pt, t, donors, receptors);
- if (BClickResult () == bcXfer)
- {
- if (--moves == 0)
- {
- if (BlobSetQuiet (receptors))
- SwapPause ("\pYou Win");
- else
- SwapPause ("\pYou Lose");
- }
- else
- {
- MovesLeft (moves, s);
- StatusMesg (s);
- }
- }
- }
- }
-
-
- static pascal void
- Update (Boolean resized)
- {
- DrawBlobSet (receptors);
- StatusMesg (statusStr);
- }
-
-
- /*
- * Select configuration: 4, 6, or 8 coins (2, 3, or 4 on each side).
- * If the number of coins on each side is n, the number of moves
- * to solve is (n+1)^2 - 1.
- */
-
- static pascal void
- DoConfiguration (short item)
- {
- nPieces = 2 * item + 3; /* 1->5, 2->7, 3->9 pieces */
- nMoves = (item + 2) * (item + 2) - 1;
- Reset ();
- }
-
-
- static pascal void
- Activate (Boolean active)
- {
- if (active)
- {
- SetDragRects (wind);
- SetBCPermissions (false, true, false, false, false); /* xfer only */
- cnfgMenu = GetMenu (swapCnfgMenuRes);
- SkelMenu (cnfgMenu, DoConfiguration, DoMClobber, false, true);
- }
- else
- SkelRmveMenu (cnfgMenu);
- }
-
-
- static void
- MakeDonors (void)
- {
- BlobHandle b;
- Rect r;
-
- donors = NewBlobSet ();
- b = NewBlob (donors, true, infiniteGlue, false, 0L);
- OpenBlob ();
- SetRect (&r, 0, 0, pieceSize, pieceSize);
- EraseRect (&r);
- FrameRect (&r);
- InsetRect (&r, 2, 2);
- PaintOval (&r);
- InsetRect (&r, -2, -2);
- CloseRectBlob (b, &r, &r);
- b = NewBlob (donors, true, infiniteGlue, false, 0L);
- OpenBlob ();
- PaintRect (&r);
- InsetRect (&r, 2, 2);
- EraseOval (&r);
- InsetRect (&r, -2, -2);
- CloseRectBlob (b, &r, &r);
- }
-
-
- void
- SwapInit (void)
- {
- SkelWindow (wind = GetDemoWind (swapWindRes),
- Mouse, /* mouse clicks */
- nil, /* key clicks */
- Update, /* updates */
- Activate, /* activate/deactivate events */
- nil, /* close window */
- DoWClobber, /* dispose of window */
- nil, /* idle proc */
- false); /* irrelevant, since no idle proc */
-
- hMid = wind->portRect.right / 2;
-
- MakeDonors ();
- Reset ();
-
- MakeFrontWind (wind);
- }
-